4.2.4 文件

multipart/form-data 编码通常用于实现文件上传功能,这种功能需要用到 file 类型的 input 标签。代码清单4-5给出的就是之前展示过的客户端表单在实现了文件上传功能之后的样子,其中以加粗方式呈现的是新增或者经过修改的代码。

代码清单4-5 文件上传

< html>
 < head>
  < meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  < title>Go Web Programming< /title>
 < /head>
 < body>
  < form action="http://localhost:8080/process?hello=world&thread=123"
 method="post" enctype="multipart/form-data">
   < input type="text" name="hello" value="sau sheong"/>
   < input type="text" name="post" value="456"/>
   < input type="file" name="uploaded">
   < input type="submit">
  < /form>
 < /body>
< /html>

为了能够接收表单上传的文件,处理器函数也需要做相应的修改,具体见代码清单4-6。

代码清单4-6 通过 MultipartForm 字段接收用户上传的文件

package main
import (
  "fmt"
  "io/ioutil"
  "net/http"
)
func process(w http.ResponseWriter, r *http.Request) {
  r.ParseMultipartForm(1024)
  fileHeader := r.MultipartForm.File["uploaded"][0]
  file, err := fileHeader.Open()
  if err == nil {
    data, err := ioutil.ReadAll(file)
    if err == nil {
      fmt.Fprintln(w, string(data))
    }
  }
}
func main() {
  server := http.Server{
    Addr: "127.0.0.1:8080",
  }
  http.HandleFunc("/process", process)
  server.ListenAndServe()
}

正如之前所说,服务器在处理文件上传时首先要做的就是执行 ParseMultipartForm 方法,接着从 MultipartForm 字段的 File 字段里面取出文件头 FileHeader ,然后通过调用文件头的 Open 方法来打开文件。在此之后,服务器会将文件的内容读取到一个字节数组中,并将这个字节数组的内容打印出来。现在,如果我们向服务器上传一个纯文本文件,那么服务器将把这个文件的内容打印在浏览器上。

FormValue 方法和 PostFormValue 方法类似, net/http 库也提供了一个 FormFile 方法,它可以快速地获取被上传的文件: FormFile 方法在被调用时将返回给定键的第一个值,因此它在客户端只上传了一个文件的情况下,使用起来会非常方便。代码清单4-7展示了一个使用 FormFile 方法的例子。

代码清单4-7 使用 FormFile 方法获取被上传的文件

func process(w http.ResponseWriter, r *http.Request) {
  file, _, err := r.FormFile("uploaded")
  if err == nil {
    data, err := ioutil.ReadAll(file)
    if err == nil {
      fmt.Fprintln(w, string(data))
    }
  }
}

正如代码所示, FormFile 方法将同时返回文件和文件头作为结果。用户在使用 FormFile 方法时,将不再需要手动调用 ParseMultipartForm 方法,只需要对返回的文件进行处理即可。

results matching ""

    No results matching ""